package client

import (
	. "chess_platform/internal/common"
	"fmt"
	"github.com/astaxie/beego/orm"
)

//玩家战绩记录(需要按天来查), 没必要做缓存,因为每个玩家查找的是自己的战绩，并且不会频繁查找
func PlayerRecord(p ListParams, uid, clubId, day int64, multiOrm ...orm.Ormer) ([]orm.Params, int64, error) {
	/*
		1. isclose,0未结束1正常结束2过期结束3投票解散
		2. 判断条件只要是不等于0就行了，因为没有数据的国华会把它删除掉，所以剩下的都是有数据的
	*/
	limit := (p.PageIndex - 1) * p.PageSize
	start, end := StartEndTimeByTimestamp(day)
	condition := fmt.Sprintf("rl.uid = %v AND r.isclose != 0 AND r.endtime >= %v AND r.endtime <= %v",
		uid, start, end)
	if clubId != 0 {
		condition = condition + fmt.Sprintf(" AND r.clubid = %v ", clubId)
	}

	sql := fmt.Sprintf(`
		SELECT
			r.tableid,r.hostid,r.clubid,r.createtime,r.starttime,r.endtime,
			r.passwd,r.dueround,r.gametype,r.playtype,r.gameinfo,r.createtype
		FROM
			%v AS rl
		LEFT JOIN
			%v AS r
		ON r.tableid= rl.tableid
		WHERE
			%v
		ORDER BY
			r.endtime DESC
		LIMIT ?,?`,
		TableRoomLog, TableRoom, condition)
	o := NewOrm(multiOrm, DBChess)
	var room []orm.Params
	n, err := o.Raw(sql, limit, p.PageSize).Values(&room)
	if err != nil || n == 0 { //没有数据可查
		return room, 0, err
	}
	sql = fmt.Sprintf(`
		SELECT
			COUNT(1)
		FROM
			%v AS rl
		LEFT JOIN
			%v AS r
		ON r.tableid= rl.tableid
		WHERE
			%v`,
		TableRoomLog, TableRoom, condition)
	var count int64
	err = o.Raw(sql).QueryRow(&count)
	if CheckError(err) {
		return room, 0, err
	}
	return room, count, nil
}

//亲友圈战绩记录(按天查询)，这个实时数据产生太快，没法做缓存，倒是可是限制下查询次数
func ClubRecord(p ListParams, clubId, day int64, multiOrm ...orm.Ormer) ([]orm.Params, int64, error) {
	/*
		    1. isclose,0未结束1正常结束2过期结束3投票解散
			2. 判断条件只要是不等于0就行了，因为没有数据的国华会把它删除掉，所以剩下的都是有数据的
	*/
	start, end := StartEndTimeByTimestamp(day)
	limit := (p.PageIndex - 1) * p.PageSize
	sql := fmt.Sprintf(`
		SELECT
			tableid,hostid,clubid,createtime,starttime,endtime,
			passwd,dueround,gametype,playtype,gameinfo,createtype
		FROM
			%v
		WHERE
			clubid = %v AND isclose != 0 AND endtime >= %v AND endtime <= %v
		ORDER BY
			endtime DESC
		LIMIT ?,?`,
		TableRoom, clubId, start, end)
	o := NewOrm(multiOrm, DBChess)
	var room []orm.Params
	n, err := o.Raw(sql, limit, p.PageSize).Values(&room)
	if err != nil || n == 0 { //没有数据可查
		return room, 0, err
	}
	sql = fmt.Sprintf(`
		SELECT
			COUNT(1)
		FROM
			%v
		WHERE
			clubid = %v AND isclose != 0 AND endtime >= %v AND endtime <= %v`,
		TableRoom, clubId, start, end)
	var count int64
	err = o.Raw(sql).QueryRow(&count)
	if CheckError(err) {
		return room, 0, err
	}

	return room, count, nil
}

//指定俱乐部指定某天获取
func ClubTableCard(clubId, day int64) (int64, int64) {
	var sql string
	var o orm.Ormer
	if !IsToday(day) {
		_, end := StartEndTimeByTimestamp(day)
		sql = fmt.Sprintf("SELECT `table`,`card` FROM %v WHERE create_time = %v AND club_id = %v",
			TableDayClub, end-1, clubId)
		o = NewDBOrm(DBChessLog)
	} else {
		sql = fmt.Sprintf(`
			SELECT
				day_table,day_card
			FROM
				%v
			WHERE
				id = %v
		`, TableClub, clubId)
		o = NewDBOrm(DBChess)
	}
	var table, card int64
	o.Raw(sql).QueryRow(&table, &card)
	return table, card
}

//亲友圈总战绩记录(按天查询),当天每个用户的总战绩
func TotalClubRecord(p ListParams, clubId, day int64, multiOrm ...orm.Ormer) ([]orm.Params, int64, error) {
	/*
		    1. isclose,0未结束1正常结束2过期结束3投票解散
			2. 判断条件只要是不等于0就行了，因为没有数据的国华会把它删除掉，所以剩下的都是有数据的
	*/
	start, end := StartEndTimeByTimestamp(day)
	limit := (p.PageIndex - 1) * p.PageSize
	sql := fmt.Sprintf(`
		SELECT
			rl.uid,COUNT(1) AS play,
			IF(SUM(rl.is_win) is NULL,0,SUM(rl.is_win)) AS is_win,
			IF(SUM(rl.score) is NULL,0,SUM(rl.score)) AS score,
			IF(SUM(rl.bigwin) is NULL,0,SUM(rl.bigwin)) AS bigwin
		FROM
			%v AS r
		INNER JOIN
			%v AS rl
		ON r.tableid = rl.tableid
		WHERE
			r.clubid = %v AND r.isclose != 0 AND r.endtime >= %v AND r.endtime <= %v
		GROUP BY
			rl.uid
		ORDER BY
			bigwin DESC,score DESC,uid ASC
		LIMIT ?,?`,
		TableRoom, TableRoomLog, clubId, start, end)
	o := NewOrm(multiOrm, DBChess)
	var room []orm.Params
	n, err := o.Raw(sql, limit, p.PageSize).Values(&room)
	if err != nil || n == 0 { //没有数据可查
		return room, 0, err
	}
	sql = fmt.Sprintf(`
		SELECT
			COUNT(DISTINCT rl.uid)
		FROM
			%v AS r
		INNER JOIN
			%v AS rl
		ON r.tableid = rl.tableid
		WHERE
			r.clubid = %v AND r.isclose != 0 AND r.endtime >= %v AND r.endtime <= %v
		`,
		TableRoom, TableRoomLog, clubId, start, end)
	var count int64
	err = o.Raw(sql).QueryRow(&count)
	if CheckError(err) {
		return room, count, err
	}

	return room, count, nil
}

//亲友圈总战绩记录(按天查询),当天每个用户的总战绩(版本2)
func TotalClubRecord2(p ListParams, clubId, startDay, endDay int64, multiOrm ...orm.Ormer) ([]orm.Params, int64, error) {
	/*
		    1. isclose,0未结束1正常结束2过期结束3投票解散
			2. 判断条件只要是不等于0就行了，因为没有数据的国华会把它删除掉，所以剩下的都是有数据的
	*/
	start, _ := StartEndTimeByTimestamp(startDay)
	_, end := StartEndTimeByTimestamp(endDay)
	limit := (p.PageIndex - 1) * p.PageSize
	sql := fmt.Sprintf(`
		SELECT
			rl.uid,COUNT(1) AS play,
			IF(SUM(rl.is_win) is NULL,0,SUM(rl.is_win)) AS is_win,
			IF(SUM(rl.score) is NULL,0,SUM(rl.score)) AS score,
			IF(SUM(rl.bigwin) is NULL,0,SUM(rl.bigwin)) AS bigwin
		FROM
			%v AS r
		INNER JOIN
			%v AS rl
		ON r.tableid = rl.tableid
		WHERE
			r.clubid = %v AND r.isclose != 0 AND r.endtime >= %v AND r.endtime <= %v
		GROUP BY
			rl.uid
		ORDER BY
			bigwin DESC,score DESC,uid ASC
		LIMIT ?,?`,
		TableRoom, TableRoomLog, clubId, start, end)
	o := NewOrm(multiOrm, DBChess)
	var room []orm.Params
	n, err := o.Raw(sql, limit, p.PageSize).Values(&room)
	if err != nil || n == 0 { //没有数据可查
		return room, 0, err
	}
	sql = fmt.Sprintf(`
		SELECT
			COUNT(DISTINCT rl.uid)
		FROM
			%v AS r
		INNER JOIN
			%v AS rl
		ON r.tableid = rl.tableid
		WHERE
			r.clubid = %v AND r.isclose != 0 AND r.endtime >= %v AND r.endtime <= %v
		`,
		TableRoom, TableRoomLog, clubId, start, end)
	var count int64
	err = o.Raw(sql).QueryRow(&count)
	if CheckError(err) {
		return room, count, err
	}

	return room, count, nil
}

//指定俱乐部指定某天获取(版本2)
func ClubTableCard2(clubId, startDay, endDay int64) (int64, int64) {
	start, _ := StartEndTimeByTimestamp(startDay)
	_, end := StartEndTimeByTimestamp(endDay)
	var table, card int64
	/*
		1.开始时间与结束时间都是今天
		2.开始时间与结束时间都不是今天
		3.开始时间不是今天，结束时间是今天

	*/
	if !IsToday(startDay) && !IsToday(endDay) {
		sql := fmt.Sprintf(`
			SELECT
				IF(SUM(table) is NULL,0,SUM(table)) AS table,
				IF(SUM(card) is NULL,0,SUM(card)) AS card
			FROM
				%v
			WHERE
				create_time >= %v AND create_time <= %v AND club_id = %v`,
			TableDayClub, start, end, clubId)
		o := NewDBOrm(DBChessLog)
		o.Raw(sql).QueryRow(&table, &card)
		return table, card
	} else if IsToday(startDay) {
		sql := fmt.Sprintf(`
			SELECT
				day_table,day_card
			FROM
				%v
			WHERE
				id = %v
		`, TableClub, clubId)
		o := NewDBOrm(DBChess)
		o.Raw(sql).QueryRow(&table, &card)
		return table, card
	} else { //开始时间不是今天，结束时间是今天
		sql := fmt.Sprintf(`
			SELECT
				IF(SUM(table) is NULL,0,SUM(table)) AS table,
				IF(SUM(card) is NULL,0,SUM(card)) AS card
			FROM
				%v
			WHERE
				create_time >= %v AND create_time <= %v AND club_id = %v`,
			TableDayClub, start, end, clubId)
		o := NewDBOrm(DBChessLog)
		o.Raw(sql).QueryRow(&table, &card)
		var tt, tc int64
		sql = fmt.Sprintf(`
			SELECT
				day_table,day_card
			FROM
				%v
			WHERE
				id = %v
		`, TableClub, clubId)
		o1 := NewDBOrm(DBChess)
		o1.Raw(sql).QueryRow(&tt, &tc)
		return table + tt, card + tc
	}

}

// 根据桌子ID查询桌子信息
func RoomInfoById(tableId int64, multiOrm ...orm.Ormer) (*Table, error) {
	sql := fmt.Sprintf(`
		SELECT
			*
		FROM
			%v
		WHERE
			tableid = ?
		LIMIT 1
		`, TableRoom)
	o := NewOrm(multiOrm, DBChess)
	var rm Table
	err := o.Raw(sql, tableId).QueryRow(&rm)
	if CheckNoExist(err) {
		return nil, nil
	}
	return &rm, err
}

//玩家开房记录
func RoomLog(p ListParams, uid, gameType int64, multiOrm ...orm.Ormer) ([]orm.Params, int64, error) {
	limit := (p.PageIndex - 1) * p.PageSize
	var condition string
	if gameType != 0 {
		condition = fmt.Sprintf(" gametype = %v AND hostid = %v", gameType, uid)
	} else {
		condition = fmt.Sprintf(" hostid = %v", uid)
	}

	sql := fmt.Sprintf(`
		SELECT
			*
		FROM
			%v
		WHERE
			%v
		ORDER BY
			tableid DESC
		LIMIT ?,?
		`, TableRoom, condition)
	o := NewOrm(multiOrm, DBChess)
	var room []orm.Params
	n, err := o.Raw(sql, limit, p.PageSize).Values(&room)
	if err != nil || n == 0 { //没有数据可查
		return room, 0, err
	}
	sql = fmt.Sprintf(`
		SELECT
			COUNT(1)
		FROM
			%v
		WHERE
			%v`,
		TableRoom, condition)
	var count int64
	err = o.Raw(sql).QueryRow(&count)
	if CheckError(err) {
		return room, 0, err
	}
	return room, count, nil
}

// 通过桌子ID获得游戏每局信息
func RecordDetail(tableId int64, multiOrm ...orm.Ormer) ([]orm.Params, error) {
	var (
		startTime int64
		endTime   int64
	)
	sql := fmt.Sprintf(`
		SELECT starttime,endtime FROM %v WHERE tableid = %v `, TableRoom, tableId)
	var res []orm.Params
	o := NewOrm(multiOrm, DBChess)
	err := o.Raw(sql).QueryRow(&startTime, &endTime)
	if CheckError(err) {
		return res, err
	}
	if startTime == 0 { //开了房在那还没有开始打，所以没有战绩可查
		return res, nil
	}

	bTable := GetTableByTimestamp(TableDayGame, startTime)
	eTable := GetTableByTimestamp(TableDayGame, endTime)

	where := fmt.Sprintf(" WHERE tid=%v ", tableId)
	if bTable == eTable || endTime < startTime { //打牌开始时间与结束时间在同一天, endTime < startTime 表示已经开打了，但还没有结束，所以endTime = 0
		sql = fmt.Sprintf("SELECT * FROM %v %v", bTable, where)
	} else { //跨天，一般跨一天，跨多天的几乎不可能出现，出现了就只有显示开始的一天与结束的那天，无所谓了
		sql = fmt.Sprintf("(SELECT * FROM %v %v ) UNION (SELECT * FROM %v %v)", bTable, where, eTable, where)
	}
	og := NewDBOrm(DBChessLog)
	_, err = og.Raw(sql).Values(&res)
	return res, err
}

// 获取战报回放
func GamePlayback(chessID string) (string, error) {
	key := fmt.Sprintf("%v%v", KeyGameRecord, chessID)
	ok, err := Redis.Exists(key)
	if err != nil {
		return "", err
	}
	if !ok {
		return "", MsgErrDataNotFound
	}
	ret, err := Redis.GetString(key)
	if err != nil {
		return "", err
	}
	return ret, nil
}
